package com.ljx.rbac.util;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.ljx.rbac.domain.dto.UserDto;
import com.ljx.rbac.domain.entity.Menu;
import com.ljx.rbac.domain.entity.Permission;
import com.ljx.rbac.domain.entity.Role;
import com.ljx.rbac.exception.ApiException;
import com.ljx.rbac.service.MenuService;
import com.ljx.rbac.service.PermissionService;
import com.ljx.rbac.service.RoleService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.DefaultJwtBuilder;

import java.time.Duration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: LiJunXi
 * @Description:
 * @Date: 2024-10-02  00:14
 */
public class UserUtil {

    private static String USER_KEY = "userInfo:";

    public static Cache<Object, Object> userCache = Caffeine.newBuilder()
            .expireAfterWrite(Duration.ofHours(2))
            .build();

    public static void setUserCache(UserDto userDto) {
        userCache.put(USER_KEY + userDto.getId(), JSONUtil.toJsonStr(userDto));
    }

    public static UserDto getUser(Long userId) {
        return JSONUtil.toBean((String) userCache.getIfPresent(USER_KEY + userId), UserDto.class);
    }

    private static final String SECRET = "eyJqdGkiOiI0MDQiLCJzdWIiOiLpgqLnq4vosbkiL";

    public static String createToken(Long userId) {
        Map<String, Object> map = new HashMap<>();
        map.put("userId", userId);
        return Jwts.builder()
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .setClaims(map)
                .compact();
    }

    public static UserDto parseToken(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(SECRET)
                .parseClaimsJws(token)
                .getBody();
        Long userId = Long.parseLong(claims.get("userId").toString());
        String userStr = (String) userCache.getIfPresent(USER_KEY + userId);
        if (StrUtil.isEmpty(userStr)) {
            throw new ApiException("身份解析失败");
        }
        return JSONUtil.toBean(userStr, UserDto.class);
    }

    public static List<Role> tryToGetUserRole(Long userId) {
        RoleService roleService = SpringUtil.getBean(RoleService.class);
        List<Long> roleIds = roleService.getUserRoleIdByUserId(userId);
        return roleService.getRoleByIds(roleIds);
    }

    public static List<Permission> tryToGetUserPermission(Long userId) {
        PermissionService permissionService = SpringUtil.getBean(PermissionService.class);
        List<Long> roles = tryToGetUserRole(userId).stream().map(Role::getId).collect(Collectors.toList());
        List<Long> permissionByRoleIds = permissionService.getPermissionIdByRoleIds(roles);
        return permissionService.getPermissionByIds(permissionByRoleIds);
    }

    public static List<Menu> tryToGetUserMenu(Long userId) {
        MenuService menuService = SpringUtil.getBean(MenuService.class);
        List<Long> roles = tryToGetUserRole(userId).stream().map(Role::getId).collect(Collectors.toList());
        List<Long> menuIds = menuService.getMenuIdByRoleIds(roles);
        return menuService.getMenuByIds(menuIds);
    }

}
